package com.anlogic.sdk.efuse.ui;

import java.io.File;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidKeySpecException;

import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import com.anlogic.sdk.efuse.model.AuthType;
import com.anlogic.sdk.efuse.model.EncType;
import com.anlogic.sdk.efuse.model.GroupId;
import com.anlogic.sdk.efuse.model.ProgramEfuseModel;
import com.anlogic.sdk.utils.ECCUtils;

public class ProgramEfuseComposite {
	Text encKeyText;
	Button encKeyButton;
	Text ppkText;
	Button ppkButton;
	Combo encType;
	Combo authType;

	Button encKeyWriteLock;
	Button ppkWriteLock;

	Button revokeFirstEncKey;
	Button revokeFirstPpk;

	ProgramEfuseModel model;

	GroupId groupId;

	private IUIValidator uiValidator;

	private Composite parentComp;

	ProgramEfuseComposite(Composite parent, ProgramEfuseModel model, GroupId groupId) {
		this.model = model;
		this.groupId = groupId;
		createUI(parent);
		this.parentComp = parent;
	}

	private void createUI(Composite parent) {
		Group group = new Group(parent, SWT.NONE);
		group.setText(String.format("%s Group", groupId.getName()));
		GridLayout layout = new GridLayout(3, false);
		group.setLayout(layout);
		GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
		group.setLayoutData(gd);
		group.setForeground(new Color(null, 0, 0, 255));

		Label encryptyKeyLabel = new Label(group, SWT.NULL);
		encryptyKeyLabel.setText("Encrypty Key:");
		encKeyText = new Text(group, SWT.BORDER);
		GridDataFactory.fillDefaults().grab(true, false).applyTo((Control) encKeyText);
		encKeyButton = new Button(group, SWT.PUSH);
		encKeyButton.setText("Browse");

		Label ppkLabel = new Label(group, SWT.NULL);
		ppkLabel.setText("PPK File:");
		ppkText = new Text(group, SWT.BORDER);
		GridDataFactory.fillDefaults().grab(true, false).applyTo((Control) ppkText);
		ppkButton = new Button(group, SWT.PUSH);
		ppkButton.setText("Browse");
		
		if (groupId == GroupId.FIRST) {
			Label encTypeLabel = new Label(group, SWT.NULL);
			encTypeLabel.setText("Encrypt Type");
			encType = new Combo(group, SWT.CHECK | SWT.READ_ONLY);
			GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo((Control) encType);
			encType.setItems(EncType.getAllNames().toArray(new String[0]));
			encType.select(0);
			Label authTypeLabel = new Label(group, SWT.NULL);
			authTypeLabel.setText("Auth Type:");
			authType = new Combo(group, SWT.CHECK | SWT.READ_ONLY);
			GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo((Control) authType);
			authType.setItems(AuthType.getAllNames().toArray(new String[0]));
			authType.select(0);
		}
		
		encKeyWriteLock = new Button(group, SWT.CHECK);
		encKeyWriteLock.setText("Encrypt Key Write Lock");
		ppkWriteLock = new Button(group, SWT.CHECK);
		ppkWriteLock.setText("PPK Write Lock");
		GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo((Control) ppkWriteLock);

		if (groupId != GroupId.FIRST) {
			revokeFirstEncKey = new Button(group, SWT.CHECK);
			revokeFirstEncKey.setText("Revoke First Encrypt Key");
			revokeFirstPpk = new Button(group, SWT.CHECK);
			revokeFirstPpk.setText("Revoke First PPK");
			GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo((Control) revokeFirstPpk);
		}

		syncModel();

		addListeners();
	}

	protected void syncModel() {
		if (groupId == GroupId.FIRST) {
			this.model.setEncType(groupId, encType.getItem(encType.getSelectionIndex()));
			this.model.setAuthType(groupId, authType.getItem(authType.getSelectionIndex()));
		}
	}

	public void setEnable(boolean enabled) {
		encKeyText.setEnabled(enabled);
		encKeyButton.setEnabled(enabled);
		ppkText.setEnabled(enabled);
		ppkButton.setEnabled(enabled);
		encKeyWriteLock.setEnabled(enabled);
		ppkWriteLock.setEnabled(enabled);
		revokeFirstEncKey.setEnabled(enabled);
		revokeFirstPpk.setEnabled(enabled);
	}

	private void addListeners() {
		encKeyText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				ProgramEfuseComposite.this.model.setEncryptyKey(ProgramEfuseComposite.this.groupId,
						encKeyText.getText());
				validateUI();
			}
		});

		encKeyButton.addSelectionListener((SelectionListener) new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				FileDialog dialog = new FileDialog(parentComp.getShell(), SWT.OPEN);
				String result = dialog.open();
				if (result != null) {
					encKeyText.setText(result);
					ProgramEfuseComposite.this.model.setEncryptyKey(ProgramEfuseComposite.this.groupId, result);
					validateUI();
				}
			}
		});

		ppkText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				ProgramEfuseComposite.this.model.setPpk(ProgramEfuseComposite.this.groupId, ppkText.getText());
				refreshUI();
				validateUI();
			}
		});

		ppkButton.addSelectionListener((SelectionListener) new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				FileDialog dialog = new FileDialog(parentComp.getShell(), SWT.OPEN);
				String result = dialog.open();
				if (result != null) {
					ppkText.setText(result);
					ProgramEfuseComposite.this.model.setPpk(ProgramEfuseComposite.this.groupId, result);
					refreshUI();
					validateUI();
				}
			}
		});

		if (groupId == GroupId.FIRST) {
			encType.addSelectionListener((SelectionListener) new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					ProgramEfuseComposite.this.model.setEncType(ProgramEfuseComposite.this.groupId, encType.getItem(encType.getSelectionIndex()));
					validateUI();
				}
			});
			
			authType.addSelectionListener((SelectionListener) new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					ProgramEfuseComposite.this.model.setAuthType(ProgramEfuseComposite.this.groupId, authType.getItem(authType.getSelectionIndex()));
					validateUI();
				}
			});
		}
		
		encKeyWriteLock.addSelectionListener((SelectionListener) new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				model.setEncKeyWriteLock(ProgramEfuseComposite.this.groupId, encKeyWriteLock.getSelection());
			}
		});

		ppkWriteLock.addSelectionListener((SelectionListener) new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				model.setPpkWriteLock(ProgramEfuseComposite.this.groupId, ppkWriteLock.getSelection());
			}
		});

		if (groupId != GroupId.FIRST) {
			revokeFirstEncKey.addSelectionListener((SelectionListener) new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					model.setRevokeFirstEncKey(revokeFirstEncKey.getSelection());
				}
			});

			revokeFirstPpk.addSelectionListener((SelectionListener) new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					model.setRevokeFirstPpk(revokeFirstPpk.getSelection());
				}
			});
		}
	}

	public void refreshUI() {
		String ppkPath = this.model.getPpk(groupId);
		if (ppkPath != null && !ppkPath.isEmpty()) {
			File file = new File(ppkPath);
			if (file.exists() && file.isFile()) {
				try {
					String algorithm = ECCUtils.getPublicKeyAlgorithm(ppkPath);
					if (algorithm.equals(ECCUtils.ECDSA256)) {
						String[] encTypeItems = {EncType.HEADER.getName(), EncType.AES256.getName()};
						String[] authTypeItems = {AuthType.HEADER.getName(), AuthType.ECDSA256.getName()};
						encType.setItems(encTypeItems);
						authType.setItems(authTypeItems);
						encType.select(0);
						authType.select(0);
					} else if (algorithm.equals(ECCUtils.SM2)) {
						String[] encTypeItems = {EncType.HEADER.getName(), EncType.SM4.getName()};
						String[] authTypeItems = {AuthType.HEADER.getName(), AuthType.SM2.getName()};
						encType.setItems(encTypeItems);
						authType.setItems(authTypeItems);
						encType.select(0);
						authType.select(0);
					}
				} catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeySpecException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
	public void validateUI() {
		if (this.uiValidator != null)
			this.uiValidator.validate();
	}

	public void setUiValidator(IUIValidator uiValidator) {
		this.uiValidator = uiValidator;
	}

}
